package errors

import (
	"fmt"
)

/*
// errInfo 是错误的 JSON 表示。

	type errInfo struct {
		// err 是错误摘要。
		err  string
		code int
		// msg 是来自错误码的扩展信息。
		msg   string
		stack *stack
	}

// list 以递归的方式扁平化调用栈。
func list(e error) []error { // TODO ： 与 Cause 函数一样都是递归实现，需要去重。

		ret := []error{}

		if e != nil {
			if wrapped, ok := e.(interface{ Unwrap() error }); ok {
				ret = append(ret, e)
				ret = append(ret, list(wrapped.Unwrap())...)
			} else {
				ret = append(ret, e)
			}
		}

		return ret
	}

// buildErrorInfo 根据错误的具体类型转换为 JSON 表示。

	func buildErrorInfo(err error) *errInfo {
		var ei *errInfo

		switch actualErr := err.(type) {
		case *fundamental:
			coder, ok := _codes[actualErr.code]
			if !ok {
				coder = _unknownCoder
			}

			ei = &errInfo{
				err:   actualErr.Error(),
				code:  coder.Code(),
				msg:   coder.String(),
				stack: actualErr.stack,
			}
		case withStack:
			wci = &withCodeInfo{
				code:  _unknownCoder.Code(),
				msg:   actualErr.Error(),
				err:   actualErr.Error(),
				stack: actualErr.stack,
			}
		case *withCode:
			// 错误码是通过注册的方式扩展到错误包的，因此其取值应该从已经注册的错误
			// 码中获取，编码中使用的未正确定义的错误码应该被归类为 _unknownCoder 。
			coder, ok := _codes[actualErr.code]
			if !ok {
				coder = _unknownCoder
			}

			msg := coder.String()
			if msg == "" {
				msg = actualErr.Error()
			}

			wci = &withCodeInfo{
				code: coder.Code(),
				msg:  msg,
				// 与从 withStack 类型构建错误的方式一致， withStack 的 Error 方法是
				// 嵌入的，实际来自于被包装的错误， 而对于 withCode 包装来说， err
				// 字段是创建或者传递错误的动机。
				err:   actualErr.Error(),
				stack: actualErr.stack,
			}
		default:
			wci = &withCodeInfo{
				code: _unknownCoder.Code(),
				msg:  actualErr.Error(),
				err:  actualErr.Error(),
			}

		}

		return wci
	}

func format(k int, jsonData []map[string]any, str *bytes.Buffer, wcInfo *withCodeInfo,

		sep string, flagDetail, flagTrace, flagJSON bool) ([]map[string]any, *bytes.Buffer) {
		if flagJSON {
			data := map[string]any{}
			if flagDetail || flagTrace {
				data = map[string]any{
					"msg":  wcInfo.msg,
					"code": wcInfo.code,
					"err":  wcInfo.err,
				}

				// 以字符串的方式构建 caller 。
				caller := fmt.Sprintf("#%d", k)
				if wcInfo.stack != nil {
					f := Frame((*wcInfo.stack)[0])
					caller = fmt.Sprintf("%s %s:%d (%s)",
						caller,
						f.file(),
						f.line(),
						f.name(),
					)
				}

				data["caller"] = caller
			} else {
				data["err"] = wcInfo.err
			}

			jsonData = append(jsonData, data)
		} else {
			if flagDetail || flagTrace {
				if wcInfo.stack != nil {
					f := Frame((*wcInfo.stack)[0])
					fmt.Fprintf(str, "%s%s - #%d [%s:%d (%s)] (%d) %s",
						sep,
						wcInfo.err,
						k,
						f.file(),
						f.line(),
						f.name(),
						wcInfo.code,
						wcInfo.msg,
					)
				} else {
					fmt.Fprintf(str, "%s%s - #%d %s", sep, wcInfo.err, k, wcInfo.msg)
				}
			} else {
				fmt.Fprintf(str, wcInfo.msg)
			}
		}

		return jsonData, str
	}
*/

func codeInfo(code int) string {
	coder, ok := _codes[code]
	if !ok {
		coder = _unknownCode
	}

	return fmt.Sprintf("code:%d,httpstatus:%d,msg:%s,ref:%s",
		coder.GetCode(),
		coder.GetHTTPStatus(),
		coder.String(),
		coder.GetReference(),
	)
}
